#include <algorithm>
#include "EditorGameState.h"
#include "OrientationComponent.h"
#include "GraphicalComponent.h"
#include "RigidBodyComponent.h"
#include "SelectableComponent.h"
#include "BoundingSphere.h"
#include "Library.h"
#include "SceneGraph.h"
#include "OnMouseLeftDownEvent.h"
#include "OnMouseMoveEvent.h"
#include "OnKeyPressEvent.h"
#include "OnKeyReleaseEvent.h"
#include "ModelFactory.h"
#include "ObjModelFile.h"
#include "Settings.h"
#include "IRenderer.h"
#include "Terrain.h"
#include "LoadTGA.h"
#include "TriangleMesh.h"
#include "BoundingSphere.h"
#include "GUIListBox.h"
#include "GUIListBoxItem.h"
#include "GUIMenu.h"
#include "LightNode.h"
#include "WaypointComponent.h"
#include "PathfinderComponent.h"
#include "TaskManager.h"

EditorGameState::EditorGameState( Pointer<CameraNode>& cameraNode ) : m_entityCounter(0), m_selectables(new System()), m_selected(0), m_cameraNode(cameraNode)
{
	m_inRunningGameState = false;
	m_running = false;
	m_selectables->Initialize();
}
void EditorGameState::RegisterEntity( HashedString id, Pointer<Entity>& entity )
{
	m_entities.insert(Entity::Pair_t(id, entity));
}
void EditorGameState::RemoveEntity( HashedString id )
{
	Entity::Map_t::iterator it;
	if ((it = m_entities.find(id)) != m_entities.end())
	{
		m_entities.erase(it);
	}
}

bool EditorGameState::FindWaypointGroup( HashedString& name, Pointer<Pathing::Waypoint>& waypoint )
{
	for (Pathing::Waypoint::GroupMap_t::iterator it = m_waypoints.begin(); it != m_waypoints.end(); ++it)
	{
		for (Pathing::Waypoint::Vector_t::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
		{
			if (it2->getPointer() == waypoint.getPointer())
			{
				name = it->first;
				return true;
			}
		}
	}
	return false;
}
void EditorGameState::RegisterWaypoint( HashedString& group, Pointer<Pathing::Waypoint>& waypoint )
{
	Pathing::Waypoint::GroupMap_t::iterator it = m_waypoints.find(group);

	if (it == m_waypoints.end())
	{
		m_waypoints.insert(Pathing::Waypoint::GroupPair_t(group, Pathing::Waypoint::Vector_t()));
		it = m_waypoints.find(group);
	}
	it->second.push_back(waypoint);
}

Pointer<Entity> EditorGameState::RetrieveEntity( HashedString id ) const
{
	Entity::Map_t::const_iterator it;
	if ((it = m_entities.find(id)) != m_entities.end())
	{
		return it->second;
	}
	return 0;
}
void EditorGameState::CreateEntity()
{
	char buffer[25];
	_itoa_s(m_entityCounter++, buffer, 10);

	OrientationComponent* orientation = 0;
	GraphicalComponent* graphical = 0;
	SelectableComponent* selectable = 0;
	
	Pointer<IResource> resource;
	Pointer<Model> model;
	Pointer<IComponent> component;
	Pointer<Entity> entity = new Entity();
	// OrientationCompenent
	component = orientation = new OrientationComponent(entity);
	orientation->getPosition() = Maths::Vector3D(0, 0, -10);
	entity->RegisterComponent(OrientationComponent::type, component);
	
	// Find Model
	resource = Library::getSingleton().getResource(Model::type, HashedString("Default"));
	CopyPointer(resource, model);

	// GraphicalComponent
	if (model.isValid())
	{
		component = graphical = new GraphicalComponent(entity, model);
		orientation->getTransformNode()->Push_Back(graphical->getNode());
		m_cameraNode->Push_Back(orientation->getTransformNode());

		entity->RegisterComponent(GraphicalComponent::type, component);
	}
	// SelectableComponent
	
	component = selectable = new SelectableComponent(Pointer<RigidBody>(new RigidBody(1.0f, entity)), entity);
	selectable->getPosition() = new DoubleValueTrigger<Maths::Vector3D>(&orientation->getPosition(), &selectable->getBody()->getPosition());
	selectable->getBody()->AddShape(Pointer<IShape>(new BoundingSphere(1.0f)));
	entity->RegisterComponent(SelectableComponent::type, component);

	m_selectables->AddRigidBody(selectable->getBody());
	RegisterEntity(buffer, entity);

	if (this->wndSceneGraphDisplay->Visible())
	{
		DisplaySceneGraph();
	}
}
bool EditorGameState::ReceiveEvent( IEvent& event )
{
	if (event.Type() == OnMouseLeftDownEvent::type)
	{
		OnMouseLeftDownEvent& mouseEvent = static_cast<OnMouseLeftDownEvent&>(event);

		int X = mouseEvent.Coords().X;
		int Y = mouseEvent.Coords().Y;
		bool control = mouseEvent.ControlKey();
		bool shift = mouseEvent.ShiftKey();

		if (control && shift)			
		{
		} else if (control)				
		{
		} else if (shift)				
		{
		} else							// No alternate keys pressed select
		{
			SelectEntity(X, Y);

			return true;				// consume event
		}
	} 
	else if (event.Type() == OnMouseMoveEvent::type)
	{
		OnMouseMoveEvent& mouseEvent = static_cast<OnMouseMoveEvent&>(event);

		int X = mouseEvent.Coords().X;
		int Y = mouseEvent.Coords().Y;
		bool control = mouseEvent.ControlKey();
		bool shift = mouseEvent.ShiftKey();
		bool lbutton = mouseEvent.LButton();

		if (control && shift && lbutton)			// Rotate
		{
			Maths::Point<float> movement(Maths::DEGTORAD * (-(float)mouseEvent.Movement().Y), Maths::DEGTORAD * -(float)mouseEvent.Movement().X);
			Maths::Vector3D currRotation = m_cameraNode->Rotation();
			currRotation.X() += movement.X;
			currRotation.Y() += movement.Y;
			m_cameraNode->setRotation(currRotation);
			return true;
		} else if (control && lbutton)				// Pan
		{
			Maths::Point<float> movement(-(float)mouseEvent.Movement().X, (float)mouseEvent.Movement().Y);
			Maths::Vector3D position = m_cameraNode->Position() + Maths::Vector3D(movement.X, movement.Y, 0);
			m_cameraNode->setPosition(position);
			return true;
		} else if (shift)							// Rotate
		{
		} else							// No alternate keys pressed select
		{
			return false;				// consume event
		}
	}
	else if (event.Type() == OnKeyPressEvent::type)
	{
		OnKeyPressEvent& keyEvent = static_cast<OnKeyPressEvent&>(event);
		
		if (keyEvent.Key() == 'W')
		{
			Maths::Vector3D distance = Maths::Quaternion::Forward * Maths::Vector3D(0,0,1);
			Maths::Vector3D position = m_cameraNode->Position() + distance;
			m_cameraNode->setPosition(position);
		}
		
		if (keyEvent.Key() == 'S')
		{
			Maths::Vector3D distance = Maths::Quaternion::Backward * Maths::Vector3D(0,0,1);
			Maths::Vector3D position = m_cameraNode->Position() + distance;
			m_cameraNode->setPosition(position);
		}
		
		if (keyEvent.Key() == '1')
		{
			Run();
		}
		if (keyEvent.Key() == '2')
		{
			if (!m_inRunningGameState)
			{
				EnterRunningGameState();
				m_inRunningGameState = true;
			} else
			{
				ExitRunningGameState();
				m_inRunningGameState = false;
			}
		}
		return true;
	}
	else if (event.Type() == OnKeyReleaseEvent::type)
	{
		OnKeyReleaseEvent& keyEvent = static_cast<OnKeyReleaseEvent&>(event);
	
		if (keyEvent.Key() == '1')
		{
			Stop();
		}
		return true;
	}
	return false;
}
void EditorGameState::SelectEntity( int x, int y )
{
	Entity* entity = 0;
	Maths::Vector3D from;
	Maths::Vector3D to;

	m_cameraNode->Unproject(x, y, from, to);

	if (m_selectables->RayCast(from, to, (void**)&entity))
	{
		ChangeSelected(entity);
	} else
	{
		ChangeSelected(0);
	}
}
void EditorGameState::ChangeSelected( Entity* selected )
{
	m_selected = selected;
	if (selected)
	{
		this->mnuEntityProperties->Visible(true);
		this->mnuLightProperties->Visible(false);

		OrientationComponent* orientation = (OrientationComponent*)selected->FindComponent(OrientationComponent::type);
		GraphicalComponent* graphical = (GraphicalComponent*)selected->FindComponent(GraphicalComponent::type);
		SelectableComponent* selectable = (SelectableComponent*)selected->FindComponent(SelectableComponent::type);
		WaypointComponent* waypoint = (WaypointComponent*)selected->FindComponent(WaypointComponent::type);
		PathfinderComponent* pathfinder = (PathfinderComponent*)selected->FindComponent(PathfinderComponent::type);

		char buffer[25];
		sprintf_s(buffer, "%.3f", orientation->getPosition().getObject().X());
		txtPositionX->Text(std::string(buffer));
		sprintf_s(buffer, "%.3f", orientation->getPosition().getObject().Y());
		txtPositionY->Text(std::string(buffer));
		sprintf_s(buffer, "%.3f", orientation->getPosition().getObject().Z());
		txtPositionZ->Text(std::string(buffer));
		
		if (waypoint)
		{
			mitEntityWaypoint->Visible(true);
			sprintf_s(buffer, "%.3f", waypoint->Radius());
			txtWaypointRadius->Text(std::string(buffer));
		} else
			mitEntityWaypoint->Visible(false);
		
		if (pathfinder)
		{
			mitEntityPathfinder->Visible(true);
			//sprintf_s(buffer, "%.3f", waypoint->G());
			//txtWaypointRadius->Text(std::string(buffer));
		} else
			mitEntityWaypoint->Visible(false);

		for (Entity::Map_t::iterator it = m_entities.begin(); it != m_entities.end(); ++it)
		{
			if (it->second.getPointer() == selected)
			{
				txtEntityName->Text(std::string(it->first.getString()));
				break;
			}
		}
	} else
	{
		txtPositionX->DefaultText(std::string("X"));
		txtPositionY->DefaultText(std::string("Y"));
		txtPositionZ->DefaultText(std::string("Z"));
		txtEntityName->Text(std::string(""));
		this->mnuEntityProperties->Visible(false);
	}
}
void EditorGameState::SetPosition()
{
	if (m_selected)
	{
		float x, y, z;
		
		sscanf_s(txtPositionX->Text().c_str(), "%f", &x);
		sscanf_s(txtPositionY->Text().c_str(), "%f", &y);
		sscanf_s(txtPositionZ->Text().c_str(), "%f", &z);
		
		OrientationComponent* orientation = (OrientationComponent*)m_selected->FindComponent(OrientationComponent::type);
		GraphicalComponent* graphical = (GraphicalComponent*)m_selected->FindComponent(GraphicalComponent::type);
		SelectableComponent* selectable = (SelectableComponent*)m_selected->FindComponent(SelectableComponent::type);
		RigidBodyComponent* rigidbody = (RigidBodyComponent*)m_selected->FindComponent(RigidBodyComponent::type);
		
		if (selectable)
		{
			selectable->setPosition(Maths::Vector3D(x, y, z));
		}
		if (rigidbody)
		{
			rigidbody->setPosition(Maths::Vector3D(x, y, z));
		}
	}
}
void EditorGameState::CreateWaypointComponent()
{
	if (m_selected)
	{
		Pointer<IComponent> component;
		WaypointComponent* waypoint;
		// WaypointComponent
		OrientationComponent* orientation = (OrientationComponent*)(m_selected->FindComponent(OrientationComponent::type));
		component = waypoint = new WaypointComponent(m_selected);
		waypoint->BindTo(orientation->getPosition());
		waypoint->Radius(1.0f);
		m_selected->RegisterComponent(WaypointComponent::type, component);

		RegisterWaypoint(HashedString(txtWaypointGroupName->Text()), waypoint->Waypoint());

		wndCreateWaypoint->Visible(false);
		ChangeSelected(m_selected);
	}
}
void EditorGameState::SetWaypointRadius()
{
	if (m_selected && txtWaypointRadius->Text().length() > 0)
	{
		WaypointComponent* waypoint = (WaypointComponent*)m_selected->FindComponent(WaypointComponent::type);

		if (waypoint)
		{
			float value = 0;
			sscanf_s(txtWaypointRadius->Text().c_str(), "%f", &value);
			waypoint->Radius(value);
		}
	}
}
void EditorGameState::DisplayCreateWaypoint()
{
	if (m_selected)
	{
		wndCreateWaypoint->Visible(true);
		txtWaypointGroupName->Text(std::string(""));
	}
}
void EditorGameState::CancelCreateWaypoint()
{
	wndCreateWaypoint->Visible(false);
}
void EditorGameState::SetEntityName()
{
	if (m_selected && txtEntityName->Text().length() > 0)
	{
		Pointer<Entity> entity;

		for (Entity::Map_t::iterator it = m_entities.begin(); it != m_entities.end(); ++it)
		{
			if (it->second.getPointer() == m_selected)
			{
				entity = it->second;
				m_entities.erase(it->first);
				m_entities.insert(Entity::Pair_t(HashedString(txtEntityName->Text()), entity));
				break;
			}
		}
	}
}
void EditorGameState::DisplayEntityNames()
{
	unsigned int totalHeight = 0;
	unsigned int counter = 0;

	wndEntityList->Visible(true);
	lstEntityNames->ClearListBoxItems();
	Pointer<GUIListBoxItem> item;

	for (Entity::Map_t::iterator it = m_entities.begin(); it != m_entities.end(); ++it)
	{
		item = new GUIListBoxItem();
		item->Text(std::string(it->first.getString()));
		item->Dimensions(Maths::Point<unsigned int>(wndRigidBodyDisplay->Dimensions().X-2, 22));
		lstEntityNames->AddListBoxItem(item);
		totalHeight += 22;

		if (it->second.getPointer() == m_selected)
			lstEntityNames->Select(counter);

		++counter;
	}
	lstEntityNames->Dimensions(Maths::Point<unsigned int>(wndEntityList->Dimensions().X, totalHeight));
	wndEntityList->Dimensions(Maths::Point<unsigned int>(wndEntityList->Dimensions().X, totalHeight + 44));
	btnEntityDelete->Location(Maths::Point<unsigned int>(btnEntityDelete->Location().X, totalHeight + 2)); 
	btnEntityDeleteCancel->Location(Maths::Point<unsigned int>(btnEntityDeleteCancel->Location().X, totalHeight + 2)); 
}
void EditorGameState::DeleteEntityByName()
{
	Pointer<GUIListBoxItem> selected(lstEntityNames->Selected());

	if (selected.isValid())
	{
		Entity::Map_t::iterator it = m_entities.find(HashedString(selected->Text()));
		if (it != m_entities.end())
		{
			m_entities.erase(it);
			ChangeSelected(0);
		}
	}
	DisplayEntityNames();
}
void EditorGameState::HideEntityWindow()
{
	wndEntityList->Visible(false);
}
void EditorGameState::OnEntityListSelectedChange()
{
	Pointer<GUIListBoxItem> selected = lstEntityNames->Selected();
	if (selected.isValid())
	{
		Entity::Map_t::iterator it = m_entities.find(std::string(selected->Text()));
		if (it != m_entities.end())
			ChangeSelected(it->second);
	}
}

void EditorGameState::DisplayLoadTexture()
{
	wndLoadTexture->Visible(true);
	txtTextureFileName->Text(std::string(""));
}
void EditorGameState::CancelLoadTexture()
{
	wndLoadTexture->Visible(false);
}
void EditorGameState::LoadTexture(std::string fileName)
{
	int extIndex = fileName.find_last_of('.');
	std::string extension = fileName.substr(extIndex + 1);
	int lastWord = fileName.find_last_of("\\/");
	std::string name = fileName.substr(lastWord + 1, extIndex - lastWord - 1);

	if (extension == "tga")
	{
		// Load Image
		Pointer<Image> image = new Image();
		if (!LoadTGA(std::string(Settings::getSingleton().getDirectory() + fileName), *image))
			return;					// fail
		Texture texture(image);
		// Add texture to renderer
		Renderer->LoadTexture( HashedString(name), texture, true );
	}
	m_textureStrings.push_back(fileName);
}
void EditorGameState::LoadTexture()
{
	wndLoadTexture->Visible(false);

	// File name and extension
	std::string fileName = txtTextureFileName->Text();
	LoadTexture(fileName);
}
void EditorGameState::ShowLoadModelWindow()
{
	wndLoadModel->Visible(true);
	txtModelFileName->Text(std::string(""));
}
void EditorGameState::CancelLoadModel()
{
	wndLoadModel->Visible(false);
}
void EditorGameState::LoadModel()
{
	wndLoadModel->Visible(false);

	// File name and extension
	std::string fileName = txtModelFileName->Text();
	int extIndex = fileName.find_last_of('.');
	std::string extension = fileName.substr(extIndex + 1);
	
	if (extension == "obj")
	{
		int lastWord = fileName.find_last_of("\\/");
		std::string name = fileName.substr(lastWord + 1, extIndex - lastWord - 1);

		MdlFile modelFile;
		ObjModelFile file;
		if (LoadObjModelFile((Settings::getSingleton().getDirectory() + fileName).c_str(), file ))
		{
			ConvertToMdlFile(file, modelFile);
			modelFile.modelName = name;
			CreateModelFromMdl(modelFile);

			cmbModelName->AddItem(modelFile.modelName);
		}
	}
	if (extension == "mdl")
	{
		MdlFile modelFile;
		if (LoadMdlFile((Settings::getSingleton().getDirectory() + fileName), modelFile ))
		{
			CreateModelFromMdl(modelFile);
		
			cmbModelName->AddItem(modelFile.modelName);
		}
	}
}
void EditorGameState::SetGraphic()
{
	const std::string name = cmbModelName->Text();

	if (m_selected)
	{
		Pointer<IComponent> component;
		OrientationComponent* orientation = (OrientationComponent*)m_selected->FindComponent(OrientationComponent::type);
		GraphicalComponent* graphical = (GraphicalComponent*)m_selected->FindComponent(GraphicalComponent::type);
		SelectableComponent* selectable = (SelectableComponent*)m_selected->FindComponent(SelectableComponent::type);
		
		Pointer<Model> model;
		Pointer<IResource> resource = Library::getSingleton().getResource(Model::type, HashedString(name));
		if (resource.isValid())				// Found new model?
		{
			CopyPointer(resource, model);
			
			m_selected->UnregisterComponent(GraphicalComponent::type);

			component = graphical = new GraphicalComponent(m_selected, model);
			orientation->getTransformNode()->Push_Back(graphical->getNode());

			m_selected->RegisterComponent(GraphicalComponent::type, component);
		}
	}
}
void EditorGameState::ShowCreateTerrainWindow()
{
	wndCreateTerrain->Visible(true);
	txtTerrainHeightmapFileName->Text(std::string(""));
	txtTerrainName->Text(std::string(""));
	txtTerrainPixelStep->Text(std::string(""));
}
void EditorGameState::CancelCreateTerrain()
{
	wndCreateTerrain->Visible(false);
}
void EditorGameState::CreateTerrain()
{
	wndCreateTerrain->Visible(false);

	// File name and extension
	std::vector<std::string> textureArray;

	std::string fileName = txtTerrainHeightmapFileName->Text();
	std::string name = txtTerrainName->Text();
	std::string pixelStep = txtTerrainPixelStep->Text();
	std::string textures = txtTerrainTextures->Text();

	unsigned int intPixelStep = atoi(pixelStep.c_str());
	int extIndex = fileName.find_last_of('.');
	std::string extension = fileName.substr(extIndex + 1);

	unsigned int index;
	do
	{
		index = textures.find_first_of(';');
		textureArray.push_back(textures.substr(0, index));
		textures.erase(0, index+1);
	} while (index != std::string::npos);

	if (extension == "tga")
	{
		// Load Heightmap
		Pointer<Heightmap> map = new Heightmap();
		if (!LoadTGA(std::string(Settings::getSingleton().getDirectory() + fileName), *map))
			return;
		map->getPixelStep() = intPixelStep; 
		Pointer<Model> terrain = new Terrain(map);
		
		// Add terrain to Library
		Pointer<IResource> resource;
		CopyPointer(terrain, resource);
		Library::getSingleton().AddResource(HashedString(name), resource);
		cmbModelName->AddItem(name);

		for (std::vector<std::string>::iterator it = textureArray.begin(); it != textureArray.end(); ++it)
			terrain->getMeshes()[0]->getMaterial().m_textures.push_back(*it);
	}
}
void EditorGameState::AddRigidbodyShape()
{
	if (m_selected)
	{
		Pointer<IShape> mesh;

		GraphicalComponent* graphical = (GraphicalComponent*)m_selected->FindComponent(GraphicalComponent::type);
		SelectableComponent* selectable = (SelectableComponent*)m_selected->FindComponent(SelectableComponent::type);

		std::string strShape(cmbRigidBodyTypes->Text());
		strShape.erase(std::remove_if(strShape.begin(), strShape.end(), isspace), strShape.end());	// Remove spaces
		HashedString shape(strShape);
		float x = 0.0f, y = 0.0f, z = 0.0f, radius = 1.0f;
		
		if (txtBodyPositionX->Text().size() > 0)
			sscanf_s(txtBodyPositionX->Text().c_str(), "%f", &x);
		
		if (txtBodyPositionY->Text().size() > 0)
			sscanf_s(txtBodyPositionY->Text().c_str(), "%f", &y);
		
		if (txtBodyPositionZ->Text().size() > 0)
			sscanf_s(txtBodyPositionZ->Text().c_str(), "%f", &z);

		if (shape == BoundingSphere::type)
		{
			BoundingSphere* sphere = new BoundingSphere(radius);
		}
		if (shape == TriangleMesh::type)					// Must be static
		{
			ModelNode* modelNode = (ModelNode*)((INode*)graphical->getNode());
			Model* model = modelNode->getModelInstance()->getModel();
			Mesh::Vector_t& meshes = model->getMeshes();

			for (Mesh::Vector_t::iterator it = meshes.begin(); it != meshes.end(); ++it)
			{
				unsigned int offset, size, vertSize = (*it)->getVertexContainer()->getVertexDeclaration().m_vertexSize;
#pragma region FIND_ENUMPOSITION
				{
					const VertexType::Vector_t& params = (*it)->getVertexContainer()->getVertexDeclaration().m_parameters;
					unsigned int paramSize = params.size();

					for (int i = 0; i < paramSize; ++i)
					{
						if (params[i].m_parameter == enumPosition)
						{
							offset = params[i].m_offset;
							size = params[i].m_size;
							break;
						}
					}
				}
#pragma endregion

				std::vector<float> verts;

				unsigned char* ptr = (unsigned char*)((*it)->getVertexContainer()->getVertexPointer()) + offset;
				unsigned int count = (*it)->getVertexContainer()->getVerticeCount();

				for (int i = 0; i < count; ++i)		// for each vertex
				{
					for (int j = 0; j < size; ++j)
						verts.push_back(*(((float*)ptr) + j));
					ptr += vertSize;
				}

				mesh = new TriangleMesh(&verts[0], count/3);
				selectable->getBody()->setMass(0.0f);
				selectable->getBody()->AddShape(mesh);
			}
		}
	}
}
void EditorGameState::ShowRigidBodyShapes()
{
	if (m_selected)
	{
		unsigned int totalHeight = 0;
		std::string type;
		std::string details;

		GraphicalComponent* graphical = (GraphicalComponent*)m_selected->FindComponent(GraphicalComponent::type);
		SelectableComponent* selectable = (SelectableComponent*)m_selected->FindComponent(SelectableComponent::type);
		IShape::Vector_t& shapes = selectable->getBody()->getShapes();

		Pointer<GUIListBoxItem> item;
		GUIListBox* listbox = lstRigidBodyShapes;
		listbox->ClearListBoxItems();

		for (IShape::Vector_t::iterator it = shapes.begin(); it != shapes.end(); ++it)
		{
			IShape* shape = (IShape*)(*it);
			type = shape->Type().getString();

			details = (*it)->ToString();

			item = new GUIListBoxItem();
			item->Text(type + "     " + details);
			item->Dimensions(Maths::Point<unsigned int>(wndRigidBodyDisplay->Dimensions().X-2, 22));
			listbox->AddListBoxItem(item);
			totalHeight += 22;
		}
		
		listbox->Dimensions(Maths::Point<unsigned int>(wndRigidBodyDisplay->Dimensions().X, totalHeight));
		wndRigidBodyDisplay->Dimensions(Maths::Point<unsigned int>(wndRigidBodyDisplay->Dimensions().X, totalHeight + 44));
		btnRigidBodyDelete->Location(Maths::Point<unsigned int>(btnRigidBodyDelete->Location().X, totalHeight + 2)); 
		btnRigidBodyCancel->Location(Maths::Point<unsigned int>(btnRigidBodyCancel->Location().X, totalHeight + 2)); 
		btnRigidBodyDeleteAll->Location(Maths::Point<unsigned int>(btnRigidBodyDeleteAll->Location().X, totalHeight + 2));
		
		wndRigidBodyDisplay->Visible(true);
	}
}
void EditorGameState::DeleteRigidBodyShape()
{
	if (m_selected)
	{
		if (lstRigidBodyShapes->SelectedRow() != -1)
		{
			GraphicalComponent* graphical = (GraphicalComponent*)m_selected->FindComponent(GraphicalComponent::type);
			SelectableComponent* selectable = (SelectableComponent*)m_selected->FindComponent(SelectableComponent::type);
		
			selectable->getBody()->RemoveShape(lstRigidBodyShapes->SelectedRow());
			ShowRigidBodyShapes();
		}
	}
}
void EditorGameState::DeleteAllRigidBodyShapes()
{
	if (m_selected)
	{
		GraphicalComponent* graphical = (GraphicalComponent*)m_selected->FindComponent(GraphicalComponent::type);
		SelectableComponent* selectable = (SelectableComponent*)m_selected->FindComponent(SelectableComponent::type);

		selectable->getBody()->ClearShapes();
		selectable->getBody()->AddShape(Pointer<IShape>(new BoundingSphere(1.0f)));
		ShowRigidBodyShapes();
	}
}
void EditorGameState::HideRigidBodyShapes()
{
	wndRigidBodyDisplay->Visible(false);
}
void EditorGameState::DisplaySceneGraph()
{
	wndSceneGraphDisplay->Visible(true);

	INode::Vector_t& children = SceneGraph::getSingleton().getChildren();
	GUITreeNode::Vector_t& nodes = treSceneGraphNodes->Children();
	treSceneGraphNodes->Children().clear();

	CreateMenuItemsForNodeVector(nodes, children);

}
void EditorGameState::CreateMenuItemsForNodeVector(GUITreeNode::Vector_t& children, INode::Vector_t& nodes)
{
	Pointer<GUITreeNode> item;

	for (INode::Vector_t::iterator it = nodes.begin(); it != nodes.end(); ++it)
	{
		item = new GUITreeNode();
		item->Title(std::string((*it)->Type().getString()));
		children.push_back(item);
		CreateMenuItemsForNodeVector(item->Children(), (*it)->getChildren());
	}
}
void EditorGameState::CloseSceneGraph()
{
	wndSceneGraphDisplay->Visible(false);
}
bool RemoveSelectedNode( const Pointer<GUITreeNode>& selected, INode::Vector_t& graph, GUITreeNode::Vector_t& tree )
{
	for (int i = 0; i < tree.size(); ++i)
	{
		if (tree[i] == selected)
		{
			Pointer<INode> sgNode = graph[i];
			sgNode->Remove();
			return true;
		} else
		{
			if (RemoveSelectedNode(selected, graph[i]->getChildren(), tree[i]->Children()))
				return true;
		}
	}
	return false;
}
Pointer<INode> GetSelectedNode( const Pointer<GUITreeNode>& selected, INode::Vector_t& graph, const GUITreeNode::Vector_t& tree )
{
	for (int i = 0; i < tree.size(); ++i)
	{
		if (tree[i] == selected)
		{
			Pointer<INode> temp = graph[i];
			return temp;
		} else
		{
			Pointer<INode> temp = GetSelectedNode(selected, graph[i]->getChildren(), tree[i]->Children());
			if (temp.isValid())
				return temp;
		}
	}
	return Pointer<INode>(0);
}
void EditorGameState::DeleteSceneGraphNode()
{
	const Pointer<GUITreeNode> selected(treSceneGraphNodes->Selected());

	INode::Vector_t& children = SceneGraph::getSingleton().getChildren();
	GUITreeNode::Vector_t& nodes = treSceneGraphNodes->Children();

	if (RemoveSelectedNode(selected, children, nodes))
		treSceneGraphNodes->Selected() = 0;

	DisplaySceneGraph();
}
void EditorGameState::CreateLight()
{
	LightNode* light;
	Pointer<INode> node = light = new LightNode();
	m_cameraNode->Push_Back(node);
	DisplaySceneGraph();
}
void EditorGameState::OnSceneNodeChangeSelected()
{
	Pointer<GUITreeNode> selected = treSceneGraphNodes->Selected();
	Pointer<INode> node;
	if (selected == 0)
	{
		this->mnuLightProperties->Visible(false);
	} else
	{
		INode::Vector_t& children = SceneGraph::getSingleton().getChildren();
		GUITreeNode::Vector_t& nodes = treSceneGraphNodes->Children();
		Pointer<INode> node = GetSelectedNode(selected, children, nodes);
		if (node.isValid())
		{
			if (node->Type() == HashedString("LightNode"))
			{
				Pointer<LightNode> light;
				CopyPointer(node, light);
				DisplayLightProperties( light );
			}
		}
	}
}

void EditorGameState::DisplayLightProperties( Pointer<LightNode>& light )
{
	this->mnuLightProperties->Visible(true);
	this->mnuEntityProperties->Visible(false);
	char buffer[25];
	sprintf_s(buffer, "%.3f", light->getLight().m_Position[0]);
	txtLightPositionX->Text(std::string(buffer));
	sprintf_s(buffer, "%.3f", light->getLight().m_Position[1]);
	txtLightPositionY->Text(std::string(buffer));
	sprintf_s(buffer, "%.3f", light->getLight().m_Position[2]);
	txtLightPositionZ->Text(std::string(buffer));
}

void EditorGameState::SetLightPosition()
{
	Pointer<GUITreeNode> selected = treSceneGraphNodes->Selected();
	if (selected.isValid())
	{
		INode::Vector_t& children = SceneGraph::getSingleton().getChildren();
		GUITreeNode::Vector_t& nodes = treSceneGraphNodes->Children();
		Pointer<INode> node = GetSelectedNode(selected, children, nodes);
		Pointer<LightNode> light;
		CopyPointer(node, light);

		float x, y, z;
		
		sscanf_s(txtLightPositionX->Text().c_str(), "%f", &x);
		sscanf_s(txtLightPositionY->Text().c_str(), "%f", &y);
		sscanf_s(txtLightPositionZ->Text().c_str(), "%f", &z);
		
		light->getLight().m_Position[0] = x;
		light->getLight().m_Position[1] = y;
		light->getLight().m_Position[2] = z;
	}
}
void EditorGameState::DragDropSceneGraph()
{
	INode::Vector_t& children = SceneGraph::getSingleton().getChildren();
	GUITreeNode::Vector_t& nodes = treSceneGraphNodes->Children();

	Pointer<GUITreeNode> selected = treSceneGraphNodes->Selected();
	Pointer<GUITreeNode> final = treSceneGraphNodes->FinalDropLocation();

	if (selected == 0 || (selected == final))
		return;
	Pointer<INode> from = GetSelectedNode(selected, children, nodes);
	Pointer<INode> to;
	
	if (from.isValid())
	{
		if (final.isValid())
		{
			to = GetSelectedNode(final, children, nodes);
			from->Remove();
			to->Push_Back(from);
		} else
		{
			from->Remove();
			SceneGraph::getSingletonPtr()->Push_Back(from);
		}
	}
	DisplaySceneGraph();
}

void EditorGameState::DisplayUnloadState()
{
	wndUnloadState->Visible(true);
	txtUnloadStateFileName->Text(std::string(""));
}
void EditorGameState::UnloadState()
{
	UnloadGameState(txtUnloadStateFileName->Text());
	wndUnloadState->Visible(false);
}
void EditorGameState::CancelUnloadState()
{
	wndUnloadState->Visible(false);
}
void EditorGameState::DisplayLoadState()
{
	wndLoadState->Visible(true);
	txtLoadStateFileName->Text(std::string(""));
}
void EditorGameState::LoadState()
{
	LoadState(txtLoadStateFileName->Text());
	wndLoadState->Visible(false);
}
void EditorGameState::CancelLoadState()
{
	wndLoadState->Visible(false);
}
void EditorGameState::CreatePathfinderComponent()
{
	if (m_selected)
	{
		std::string text = txtWaypointName->Text();


		Pointer<IComponent> component;
		PathfinderComponent* pathfinder;
		// PathfinderComponent
		OrientationComponent* orientation = (OrientationComponent*)(m_selected->FindComponent(OrientationComponent::type));
		component = pathfinder = new PathfinderComponent(m_selected);

		Pathing::Waypoint::GroupMap_t::iterator it = m_waypoints.find(HashedString(text));

		if (it == m_waypoints.end())
			return;

		pathfinder->setWaypoints(text, (*it).second);
		if (orientation)
			pathfinder->BindTo(orientation->getPosition());
		m_selected->RegisterComponent(WaypointComponent::type, component);

		wndCreatePathfinder->Visible(false);
		ChangeSelected(m_selected);
	}
}
void EditorGameState::DeletePathfinder()
{
	if (m_selected)
	{
	}
}
void EditorGameState::DisplayCreatePathfinder()
{
	if (m_selected)
	{
		wndCreatePathfinder->Visible(true);
		txtWaypointName->Text(std::string(""));
	}
}
void EditorGameState::CancelCreatePathfinder()
{
	wndCreatePathfinder->Visible(false);
}

void EditorGameState::setTimer( Pointer<ITask>& timer )
{
	m_timer = timer;
}
void EditorGameState::setPhysics( Pointer<ITask>& physics )
{
	m_physics = physics;
}

void EditorGameState::Run()
{
	if (!m_running)
	{
		// Resume Timer
		TaskManager::getSingleton().ResumeTask(m_timer);
		// Resume Physics
		TaskManager::getSingleton().ResumeTask(m_physics);
		m_running = true;
	}
}
void EditorGameState::Stop()
{
	if (m_running)
	{
		// Suspend Timer
		TaskManager::getSingleton().SuspendTask(m_timer);
		// Suspend Physics
		TaskManager::getSingleton().SuspendTask(m_physics);
		m_running = false;
	}
}
void EditorGameState::EnterRunningGameState()
{
	wndToolbox->Visible(false);
	wndProperties->Visible(false);
	Run();
}
void EditorGameState::ExitRunningGameState()
{
	wndToolbox->Visible(true);
	wndProperties->Visible(true);
	Stop();
}